package com.ruoyi.asset.maintenance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.asset.common.scopecode.constant.ServiceCode;
import com.ruoyi.asset.common.scopecode.service.IScopeCodeService;
import com.ruoyi.asset.homepage.constant.CommunityConstant;
import com.ruoyi.asset.homepage.constant.ServiceTypeConstant;
import com.ruoyi.asset.maintenance.constant.MaintenanceDirtConstant;
import com.ruoyi.asset.maintenance.domain.IntegratedMaintenance;
import com.ruoyi.asset.maintenance.domain.bo.IntegratedMaintenanceBo;
import com.ruoyi.asset.maintenance.domain.bo.MaintenanceCommunityBo;
import com.ruoyi.asset.maintenance.domain.bo.MaintenanceProjectTypeBo;
import com.ruoyi.asset.maintenance.domain.bo.MaintenanceStatisticsBo;
import com.ruoyi.asset.maintenance.domain.vo.IntegratedMaintenanceVo;
import com.ruoyi.asset.maintenance.domain.vo.MaintenanceCommunityCountVo;
import com.ruoyi.asset.maintenance.domain.vo.MaintenanceCommunityMapVo;
import com.ruoyi.asset.maintenance.domain.vo.MaintenanceWorkStatisticsVo;
import com.ruoyi.asset.maintenance.mapper.IntegratedMaintenanceMapper;
import com.ruoyi.asset.maintenance.service.IIntegratedMaintenanceService;
import com.ruoyi.asset.tool.domain.bo.ToolStatisticsBo;
import com.ruoyi.asset.tool.service.IToolService;
import com.ruoyi.asset.workman.domain.Workman;
import com.ruoyi.asset.workman.service.IWorkmanService;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.tools.excel.MyExcelUtil;
import com.ruoyi.common.tools.excel.base.MyExcelResult;
import com.ruoyi.common.tools.excel.listener.asset.MaintenanceExcelListener;
import com.ruoyi.common.tools.utils.SerialGenerator;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.erecord.region.service.IRegionService;
import com.ruoyi.standingbook.maintenance.service.IMaintenanceService;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author 12276
 */
@RequiredArgsConstructor
@Service
public class IntegratedMaintenanceServiceImpl implements IIntegratedMaintenanceService {

    private final IntegratedMaintenanceMapper integratedMaintenanceMapper;
    private final IMaintenanceService maintenanceService;
    private IToolService toolService = SpringUtils.getBean(IToolService.class);
    private IRegionService regionService = SpringUtils.getBean(IRegionService.class);
    private IWorkmanService workmanService = SpringUtils.getBean(IWorkmanService.class);
    private ISysDictDataService sysDictDataService = SpringUtils.getBean(ISysDictDataService.class);

    private final IScopeCodeService scopeCodeService;

    private Boolean batchInsertOrUpdate(List<IntegratedMaintenance> voList) {
        return this.integratedMaintenanceMapper.insertOrUpdateBatch(voList);
    }

    @Override
    public List<String> importExcel(String excelUrl) {
        List<String> errorMsgList = new ArrayList<>();

        // 生成批次号
        final String batchNo = SerialGenerator.generator.nextId();

        // excel 处理
        MyExcelResult<IntegratedMaintenanceVo> excelResult = MyExcelUtil.getImportExcelData(batchNo, excelUrl,
            new MaintenanceExcelListener(batchNo), IntegratedMaintenanceVo.class, true);

        if (null == excelResult) {
            errorMsgList.add("未获取到要处理的数据");

            return null;
        }

        /**
         *  有解析失败就直接返回错误信息
         */
        if(!excelResult.getErrorList().isEmpty()) {
            return excelResult.getErrorList();
        }

        if (!excelResult.getList().isEmpty()) {
            List<IntegratedMaintenance> list = new ArrayList<>();
            AtomicInteger row = new AtomicInteger(0);
            excelResult.getList().forEach(e -> {
                int currentRow = row.incrementAndGet();
                if (e.getDataCheckResult().isSucess()) {
                    IntegratedMaintenance integratedMaintenance = new IntegratedMaintenance();

                    BeanCopyUtils.copy(e, integratedMaintenance);

                    IntegratedMaintenance oldLampIntegratedMaintenance = getVoByCondition(integratedMaintenance.getProjectName(),
                        integratedMaintenance.getProjectType());

                    if (oldLampIntegratedMaintenance != null) {
                        integratedMaintenance.setId(oldLampIntegratedMaintenance.getId());
                    } else {
                        String scopeCode = null;

                        try {
                            scopeCode = scopeCodeService.getNextScopeCode(ServiceCode.MAINTENANCE,
                                integratedMaintenance.getProjectType(), "");
                        } catch (Exception ex) {
                            errorMsgList.add("获取管理范围编码失败，失败原因：" + ex.getMessage());
                        }

                        integratedMaintenance.setProjectCode(scopeCode);
                    }

                    /**
                     *  如果各行数据校验通过，再遍历检查是否数据重复
                     */
                    if (excelResult.getValidateList().isEmpty()) {
                        AtomicInteger count = new AtomicInteger(0);
                        list.stream().anyMatch(f -> {
                            int currentCount = count.incrementAndGet();
                            if (f.getProjectName().equals(integratedMaintenance.getProjectName()) && f.getProjectType().equals(integratedMaintenance.getProjectType())) {
                                errorMsgList.add(String.format("第%d行数据检查失败，失败原因：与第%s行数据重复", currentRow, currentCount));
                                return true;
                            }
                            return false;
                        });
                    }

                    list.add(integratedMaintenance);
                } else {
                    errorMsgList.add(String.format("第 %d 行数据检查失败，失败原因：%s", currentRow, e.getDataCheckResult().getMsg()));
                }
            });

            if (errorMsgList.isEmpty()) {
                batchInsertOrUpdate(list);
            }
        }

        return errorMsgList;
    }

    private IntegratedMaintenance getVoByCondition(String projectName, String projectType) {
        LambdaQueryWrapper<IntegratedMaintenance> lqw = Wrappers.lambdaQuery();

        lqw.eq(IntegratedMaintenance::getProjectName, projectName);
        lqw.eq(IntegratedMaintenance::getProjectType, projectType);
        lqw.eq(IntegratedMaintenance::getDelFlag, 0);

        List<IntegratedMaintenance> list = integratedMaintenanceMapper.selectList(lqw);

        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public int deleteMaintenance(Set<Long> idsSet) {
        if (CollectionUtils.isEmpty(idsSet)) {
            return -1;
        }
        return integratedMaintenanceMapper.logicDeleteMaintenance(idsSet);
    }

    @Override
    public TableDataInfo<IntegratedMaintenanceVo> queryMaintenance(IntegratedMaintenanceBo searchBo, PageQuery pageQuery) {
        Page<IntegratedMaintenanceVo> result = integratedMaintenanceMapper.selectMaintenance(pageQuery.build(), searchBo);
        ArrayList<IntegratedMaintenanceVo> list = new ArrayList<>();
        result.getRecords().forEach(e -> {
            IntegratedMaintenanceVo integratedMaintenanceVo = new IntegratedMaintenanceVo();
            BeanCopyUtils.copy(e, integratedMaintenanceVo);
            String maintenanceType = sysDictDataService.selectDictLabel(MaintenanceDirtConstant.MAINTENANCE_TYPE, integratedMaintenanceVo.getProjectType());
            if (StringUtils.isNotBlank(maintenanceType)) {
                integratedMaintenanceVo.setProjectType(maintenanceType);
            }
            list.add(integratedMaintenanceVo);

        });
        result.setRecords(list);
        return TableDataInfo.build(result);
    }

    @Override
    public List<IntegratedMaintenanceVo> exportMaintenance(IntegratedMaintenanceBo searchBo) {
        ArrayList<IntegratedMaintenanceVo> list = new ArrayList<>();
        integratedMaintenanceMapper.exportMaintenance(searchBo).forEach(e -> {
            IntegratedMaintenanceVo integratedMaintenanceVo = new IntegratedMaintenanceVo();
            BeanCopyUtils.copy(e, integratedMaintenanceVo);
            String maintenanceType = sysDictDataService.selectDictLabel(MaintenanceDirtConstant.MAINTENANCE_TYPE, integratedMaintenanceVo.getProjectType());
            if (StringUtils.isNotBlank(maintenanceType)) {
                integratedMaintenanceVo.setProjectType(maintenanceType);
            }
            list.add(integratedMaintenanceVo);

        });
        return list;
    }

    @Override
    public MaintenanceStatisticsBo getMaintenanceCount() {
        MaintenanceStatisticsBo statisticsBo = new MaintenanceStatisticsBo();
        Integer numCount = integratedMaintenanceMapper.selectCount();
        statisticsBo.setProjectCount(numCount);
        int workCount = workmanService.getByServiceType(ServiceTypeConstant.MAINTENANCE);
        statisticsBo.setWorkerCount(workCount);
        ToolStatisticsBo toolStatisticsBo = toolService.getCountByServiceType(ServiceTypeConstant.MAINTENANCE);
        if (null != toolStatisticsBo) {
            statisticsBo.setEquipmentCount(toolStatisticsBo.getToolCount());
            statisticsBo.setVehicleCount(toolStatisticsBo.getVehicleCount());
        } else {
            statisticsBo.setEquipmentCount(0);
            statisticsBo.setVehicleCount(0);
        }
        return statisticsBo;
    }

    @Override
    public Map getMaintenanceCommunityCount() {
        HashMap<String, MaintenanceCommunityBo> map = new HashMap<>();
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(CommunityConstant.COMMUNITY_TYPE);
        List<SysDictData> data = sysDictDataService.selectDictDataList(sysDictData);
        for (SysDictData community : data) {
            String communityNo = regionService.getRegionIdByName(community.getDictLabel());
            List<MaintenanceProjectTypeBo> maintenanceProjectTypeBos = integratedMaintenanceMapper.selectCommunityCount(communityNo);
            if (maintenanceProjectTypeBos.size() > 0) {
                maintenanceProjectTypeBos.forEach(e -> {
                    String projectName = sysDictDataService.selectDictLabel(MaintenanceDirtConstant.MAINTENANCE_TYPE, e.getProjectType());
                    if (StringUtils.isNotBlank(projectName)) {
                        e.setProjectType(projectName);
                    }
                });
            }
            MaintenanceCommunityBo maintenanceCommunityBo = new MaintenanceCommunityBo();
            maintenanceCommunityBo.setMaintenanceProjectTypeBoList(maintenanceProjectTypeBos);
            ToolStatisticsBo toolCount = toolService.getCountByServiceTypeAndCommunity(ServiceTypeConstant.MAINTENANCE, communityNo);
            maintenanceCommunityBo.setToolCount(toolCount.getToolCount());
            maintenanceCommunityBo.setVehicleCount(toolCount.getVehicleCount());
            int workmanCount = workmanService.getCommunityByServiceType(ServiceTypeConstant.MAINTENANCE, communityNo);
            maintenanceCommunityBo.setWorkmanCommunity(workmanCount);
            map.put(community.getDictLabel(), maintenanceCommunityBo);
        }
        return map;
    }

    @Override
    public List<MaintenanceCommunityCountVo> getMaintenanceCountByCommunity(String date) {
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(CommunityConstant.COMMUNITY_TYPE);
        List<SysDictData> communities = sysDictDataService.selectDictDataList(sysDictData);
        ArrayList<MaintenanceCommunityCountVo> maintenanceCommunityCountVos = new ArrayList<>();
        communities.forEach(e -> {
            MaintenanceCommunityCountVo maintenanceCommunityCountVo = new MaintenanceCommunityCountVo();
            maintenanceCommunityCountVo.setCommunity(e.getDictLabel());
            String regionId = regionService.getRegionIdByName(e.getDictLabel());
            Integer numSum = integratedMaintenanceMapper.selectMaintenanceCountByCommunity(date, regionId);
            maintenanceCommunityCountVo.setNumSum(numSum.toString());
            ToolStatisticsBo toolCount = toolService.getCommunityByServiceTypeAndDate(ServiceTypeConstant.MAINTENANCE, regionId, date);
            if (null != toolCount) {
                maintenanceCommunityCountVo.setEquipmentCount(toolCount.getToolCount());
                maintenanceCommunityCountVo.setVehicleCount(toolCount.getVehicleCount());
            } else {
                maintenanceCommunityCountVo.setEquipmentCount(0);
                maintenanceCommunityCountVo.setVehicleCount(0);
            }
            int workmanCount = workmanService.getCommunityByServiceTypeAndDate(ServiceTypeConstant.MAINTENANCE, regionId, date);
            maintenanceCommunityCountVo.setWorkerCount(workmanCount);
            maintenanceCommunityCountVos.add(maintenanceCommunityCountVo);
        });
        return maintenanceCommunityCountVos;
    }

    @Override
    public MaintenanceWorkStatisticsVo getMaintenanceWorkByDate(String date) {
        MaintenanceWorkStatisticsVo statisticsVo = new MaintenanceWorkStatisticsVo();
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(CommunityConstant.COMMUNITY_TYPE);
        List<SysDictData> communities = sysDictDataService.selectDictDataList(sysDictData);
        ArrayList<Integer> totalNumList = new ArrayList<>();
        communities.forEach(e -> {
            String regionId = regionService.getRegionIdByName(e.getDictLabel());
            Integer numSum = integratedMaintenanceMapper.selectMaintenanceCountByCommunity(date, regionId);
            totalNumList.add(numSum);
        });
        Integer totalNum = totalNumList.stream().reduce(Integer::sum).orElse(0);
        statisticsVo.setTotalNum(totalNum);
        Integer sumByDate = maintenanceService.getSumByDate(date);
        if(sumByDate == null) {
            sumByDate = 0;
        }
        statisticsVo.setFinishedNumSum(sumByDate);
        Integer sumByYearAndCommunity = maintenanceService.getSumByYearAndCommunity(date, null);
        if (sumByYearAndCommunity == null) {
            sumByYearAndCommunity = 0;
        }
        statisticsVo.setSumByYear(BigDecimal.valueOf(sumByYearAndCommunity));
        return statisticsVo;
    }

    @Override
    public MaintenanceWorkStatisticsVo getMaintenanceWorkByDateAndCommunity(String date, String community) {
        MaintenanceWorkStatisticsVo statisticsVo = new MaintenanceWorkStatisticsVo();
        String regionId = regionService.getRegionIdByName(community);
        Integer numSum = integratedMaintenanceMapper.selectMaintenanceCountByCommunity(date, regionId);
        statisticsVo.setTotalNum(numSum);
        Integer sumByDate = maintenanceService.getSumByDateAndCommunity(date,community);
        if (sumByDate == null) {
            sumByDate = 0;
        }
        statisticsVo.setFinishedNumSum(sumByDate);
        Integer sumByYearAndCommunity = maintenanceService.getSumByYearAndCommunity(date, community);
        if (sumByYearAndCommunity == null) {
            sumByYearAndCommunity = 0;
        }
        statisticsVo.setSumByYear(BigDecimal.valueOf(sumByYearAndCommunity));
        return statisticsVo;
    }

    @Override
    public MaintenanceCommunityMapVo getCommunityByDate(String community, String date) {
        HashMap<String, String> map = new HashMap<>(32);
        String communityNo = regionService.getRegionIdByName(community);
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(MaintenanceDirtConstant.MAINTENANCE_TYPE);
        List<SysDictData> data = sysDictDataService.selectDictDataList(sysDictData);
        List<MaintenanceProjectTypeBo> maintenanceProjectTypeBos = integratedMaintenanceMapper.selectCommunityCount(communityNo);
        buildLampTypeMap(data, maintenanceProjectTypeBos, map);
        MaintenanceCommunityMapVo maintenanceCommunityMapVo = new MaintenanceCommunityMapVo();
        maintenanceCommunityMapVo.setMaintenanceTypeMap(map);
        ToolStatisticsBo toolCount = toolService.getCountByServiceTypeAndCommunity(ServiceTypeConstant.MAINTENANCE, communityNo);
        maintenanceCommunityMapVo.setToolCount(toolCount.getToolCount());
        maintenanceCommunityMapVo.setVehicleCount(toolCount.getVehicleCount());
        int workmanCount = workmanService.getCommunityByServiceType(ServiceTypeConstant.MAINTENANCE, communityNo);
        maintenanceCommunityMapVo.setWorkmanCommunity(workmanCount);
        return maintenanceCommunityMapVo;
    }

    @Override
    public Integer getMaintenanceByDateAndCommunity(String date, String community) {
        Integer maintenanceCount;
        if (StringUtils.isNotEmpty(community)) {
            String regionId = regionService.getRegionIdByName(community);
            maintenanceCount = integratedMaintenanceMapper.selectMaintenanceCountByCommunity(date, regionId);
        } else {
            maintenanceCount = integratedMaintenanceMapper.selectMaintenanceCountByCommunity(date, null);
        }
        if (null == maintenanceCount) maintenanceCount =0;
        return maintenanceCount;
    }

    /**
     * 组装数据
     *
     * @param data
     * @param maintenanceProjectTypeBos
     * @param map
     */
    private void buildLampTypeMap(List<SysDictData> data, List<MaintenanceProjectTypeBo> maintenanceProjectTypeBos, HashMap<String, String> map) {
        ArrayList<String> typeName = new ArrayList<>();
        for (SysDictData lampType : data) {
            if (maintenanceProjectTypeBos.size() > 0) {
                for (MaintenanceProjectTypeBo maintenanceProjectTypeBo : maintenanceProjectTypeBos) {
                    if (lampType.getDictValue().equals(maintenanceProjectTypeBo.getProjectType())) {
                        typeName.add(lampType.getDictLabel());
                        map.put(lampType.getDictLabel(), maintenanceProjectTypeBo.getProjectCount() + " ");
                    }
                }
            } else {
                map.put(lampType.getDictLabel(), "0");
            }
        }
        if (typeName.size() > 0) {
            List<String> labelList = data.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());
            labelList.removeAll(typeName);
            labelList.forEach(e -> {
                map.put(e, "0");
            });
        }
    }

}
